/**
 * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.jiadakeji.ppm.modules.business.web;

import com.jiadakeji.ppm.common.beanvalidator.BeanValidators;
import com.jiadakeji.ppm.common.config.Global;
import com.jiadakeji.ppm.common.persistence.Page;
import com.jiadakeji.ppm.common.utils.DateUtils;
import com.jiadakeji.ppm.common.utils.DecimalUtils;
import com.jiadakeji.ppm.common.utils.StringUtils;
import com.jiadakeji.ppm.common.utils.excel.ImportExcel;
import com.jiadakeji.ppm.common.web.BaseController;
import com.jiadakeji.ppm.modules.business.dao.BuildingDao;
import com.jiadakeji.ppm.modules.business.dao.CommunityDao;
import com.jiadakeji.ppm.modules.business.dao.FeeChargeDao;
import com.jiadakeji.ppm.modules.business.dao.FeeMonthDao;
import com.jiadakeji.ppm.modules.business.entity.*;
import com.jiadakeji.ppm.modules.business.service.FeeChargeService;
import com.jiadakeji.ppm.modules.business.service.FeeReceiveService;
import com.jiadakeji.ppm.modules.business.service.RoomService;
import com.jiadakeji.ppm.modules.sys.utils.DictUtils;
import com.jiadakeji.ppm.modules.sys.utils.UserUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;

/**
 * 应收台账Controller
 * @author HHAOYU
 * @version 2019-07-09
 */
@Controller
@RequestMapping(value = "${adminPath}/business/feeCharge")
public class FeeChargeController extends BaseController {

	@Autowired
	private FeeChargeService feeChargeService;
	@Autowired
	private FeeReceiveService feeReceiveService;
	@Autowired
	private RoomService roomService;
	@Autowired
	private CommunityDao communityDao;
	@Autowired
	private BuildingDao buildingDao;
	@Autowired
	private FeeMonthDao feeMonthDao;
	@Autowired
	private FeeChargeDao feeChargeDao;
	
	@ModelAttribute
	public FeeCharge get(@RequestParam(required=false) String id) {
		FeeCharge entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = feeChargeService.get(id);
		}
		if (entity == null){
			entity = new FeeCharge();
		}
		return entity;
	}
	
	@RequiresPermissions("business:feeCharge:view")
	@RequestMapping(value = {"list", ""})
	public String list(FeeCharge feeCharge, HttpServletRequest request, HttpServletResponse response, Model model) {
		Page<FeeCharge> page = feeChargeService.findPage(new Page<FeeCharge>(request, response), feeCharge);
		Double total = page.getList().stream().filter(feeCharge1 -> feeCharge1.getStatus().equals("0")).mapToDouble(FeeCharge::getTotalFee).sum();
		total = DecimalUtils.add(total,0.0);
		model.addAttribute("total",total);
		model.addAttribute("page", page);
		
		UserUtils.putCache("feeCharge", feeCharge);
		return "modules/business/feeChargeList";
	}

	@RequiresPermissions("business:feeCharge:view")
	@RequestMapping(value = "form")
	public String form(FeeCharge feeCharge, Model model) {
		FeeReceive feeReceive = new FeeReceive();
		Room r = roomService.get(feeCharge.getRoomId());
		feeReceive.setPayAmount(DecimalUtils.add(feeCharge.getTotalFee(),feeCharge.getFeebackMoney()));
		feeCharge.setFeeReceive(feeReceive);
		feeCharge.setRoom(r);
		model.addAttribute("feeCharge", feeCharge);
		return "modules/business/feeChargeForm";
	}

	@RequiresPermissions("business:feeCharge:edit")
	@RequestMapping(value = "save")
	public String save(FeeCharge feeCharge, Model model, RedirectAttributes redirectAttributes) {
		if (!beanValidator(model, feeCharge)){
			return form(feeCharge, model);
		}
		feeChargeService.save(feeCharge);
		addMessage(redirectAttributes, "保存应收台账成功");
		
		redirectAttributes.addFlashAttribute("feeCharge", UserUtils.getCache("feeCharge"));
		return "redirect:"+Global.getAdminPath()+"/business/feeCharge/?repage";
	}

	@RequiresPermissions("business:feeCharge:edit")
	@RequestMapping(value = "reCalFeeCharge")
	public String reCalFeeCharge(FeeCharge feeCharge, RedirectAttributes redirectAttributes) {
		feeChargeService.reCalFeeChargeByRoom(feeCharge);
		addMessage(redirectAttributes, "重新算费成功");

		redirectAttributes.addFlashAttribute("feeCharge", UserUtils.getCache("feeCharge"));
		return "redirect:"+Global.getAdminPath()+"/business/feeCharge/?repage";
	}

	@RequiresPermissions("business:feeCharge:edit")
	@RequestMapping(value = "formCharge")
	public String formCharge(FeeCharge feeCharge, RedirectAttributes redirectAttributes) {
		feeChargeService.reCalFeeChargeByRoom(feeCharge);
		addMessage(redirectAttributes, "重新算费成功");

		redirectAttributes.addFlashAttribute("feeCharge", UserUtils.getCache("feeCharge"));
		return "redirect:"+Global.getAdminPath()+"/business/feeCharge/?repage";
	}


	@RequiresPermissions("business:feeCharge:edit")
	@RequestMapping(value = "delete")
	public String delete(FeeCharge feeCharge, RedirectAttributes redirectAttributes) {
		feeChargeService.delete(feeCharge);
		addMessage(redirectAttributes, "删除应收台账成功");
		
		redirectAttributes.addFlashAttribute("feeCharge", UserUtils.getCache("feeCharge"));
		return "redirect:"+Global.getAdminPath()+"/business/feeCharge/?repage";
	}

	@RequiresPermissions("business:feeCharge:edit")
	@RequestMapping(value = "payFeeChargeCash")
	public String payFeeChargeCash(FeeCharge feeCharge, RedirectAttributes redirectAttributes) {
		FeeReceive feeReceive = new FeeReceive();
		feeReceive.setFeeCharge(feeCharge);
		feeReceiveService.payFeeChargeCash(feeReceive);
		addMessage(redirectAttributes, "收费成功");

		redirectAttributes.addFlashAttribute("feeCharge", UserUtils.getCache("feeCharge"));
		return "redirect:"+Global.getAdminPath()+"/business/feeCharge/?repage";
	}


	@RequiresPermissions("business:FeeCharge:edit")
	@RequestMapping(value = "import")
	@Transactional(readOnly = false)
	public String importRoom(MultipartFile file, RedirectAttributes redirectAttributes, HttpServletResponse response){
		try {
			int successNum = 0;
			int failureNum = 0;
			StringBuilder failureMsg = new StringBuilder();
			ImportExcel ei = new ImportExcel(file, 1, 0);
			String[] names =((CommonsMultipartFile) file).getOriginalFilename().split("-");
			List<Community> communityList =null;
			Community currentCommunity ;
			if(names.length>0){
				Community community = new Community();
				community.setName(names[0]);
				communityList =	communityDao.findList(community);

			}
			if(communityList!= null){
				currentCommunity = communityList.get(0);
			}else {
				failureMsg.append("不存在该小区请先在系统中建立相同名称的小区，文件名应为 小区名+ - + 任意");
				return "redirect:" + adminPath + "/business/room/?repage";
			}

			List<FeeChargeHistory> list = ei.getDataList(FeeChargeHistory.class);

			FeeMonth feeMonth = new FeeMonth();
			FeeMonth fm;
			Room room = new Room();
			Building building = new Building();
			for (FeeChargeHistory feeChargeHistory : list){
				try{
					successNum++;
					building.setCommunityId(currentCommunity.getId());
					building.setCode(feeChargeHistory.getBuildingCode());
					List<Building> buildingList = buildingDao.findList(building);
					if(buildingList != null && !buildingList.isEmpty()){
						Building bd =  buildingList.get(0);
						room.setBuildingId(bd.getId());
						room.setCode(feeChargeHistory.getRoomCode());
						List<Room> roomList = roomService.findList(room);
						if(roomList != null && !roomList.isEmpty()){
							for(int i = 0;i<feeChargeHistory.getMonthHistory();i++){
								Date currentMonth  = DateUtils.addMonths(feeChargeHistory.getBeginDate(),i);
								feeMonth.setCurrentMonth(currentMonth);
								List<FeeMonth> feeMonthList = feeMonthDao.selectFeeMonthByCurrentMonth(feeMonth);
								if(null == feeMonthList || feeMonthList.isEmpty()){
									fm = new FeeMonth();
									fm.preInsert();
									fm.setCurrentMonth(currentMonth);
									fm.setIsCurrent("0");
									fm.setStartDate(currentMonth);
									LocalDate lastLocalDate = DateUtils.tranDateToLocalDate(currentMonth).with(TemporalAdjusters.lastDayOfMonth());
									fm.setEndDate(DateUtils.tranLocalDateToDate(lastLocalDate));
									feeMonthDao.insert(fm);
								}else {
									fm = feeMonthList.get(0);
								}

								FeeCharge feeCharge = new FeeCharge();
								feeCharge.setFeeMonthId(fm.getId());
								feeCharge.setRoomId(roomList.get(0).getId());
								feeChargeDao.deleteRepeat(feeCharge);
								feeCharge.setRoomUseFlag(roomList.get(0).getUseFlag());
								feeCharge.setAvgWaterFee(feeChargeHistory.getAvgWater());
								feeCharge.setAvgElecFee(feeChargeHistory.getAvgElec());
								feeCharge.setManageFee(DecimalUtils.multiply(feeChargeHistory.getArea(),feeChargeHistory.getManageFee()));
								feeCharge.setElevatorFee( null == feeChargeHistory.getElevatorFee() ? 0.0:feeChargeHistory.getElevatorFee());
								feeCharge.setSecondPushElecFee(null == feeChargeHistory.getSecondPushFee() ? 0.0:feeChargeHistory.getSecondPushFee());
								feeCharge.setFeebackMoney(0.0);
								feeCharge.setCarMonthFee(0.0);
								Double totalFee = 0.0;
								totalFee = DecimalUtils.add(totalFee
										,feeCharge.getAvgElecFee()
										,feeCharge.getAvgWaterFee()
										,feeCharge.getElevatorFee()
										,feeCharge.getManageFee()
										,feeCharge.getSecondPushElecFee()
										,feeCharge.getCarMonthFee());
								feeCharge.setTotalFee(totalFee);
								feeCharge.setStatus("0");
								Date nowDate = new Date(System.currentTimeMillis());
								feeCharge.setPublishDate(nowDate);
								LocalDate feebackBeginDate = DateUtils.tranDateToLocalDate(nowDate).plusDays(Integer.valueOf(DictUtils.getDictValue("违约金起收天数","feeback_message","0")));
								feeCharge.setFeebackBeginDate(DateUtils.tranLocalDateToDate(feebackBeginDate));
								feeCharge.setFeebackRate(Double.valueOf(DictUtils.getDictValue("违约金比例","feeback_message","0.0001")));
								feeChargeService.save(feeCharge);

							}
						}else {
							throw new RuntimeException();
						}

					}else {
						throw new RuntimeException();
					}

				}catch(ConstraintViolationException ex){
					failureMsg.append(" 导入失败：");
					List<String> messageList = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
					for (String message : messageList){
						failureMsg.append(message+"; ");
						failureNum++;
					}
				}catch (Exception ex) {
					failureMsg.append(" 导入失败："+ex.getMessage());
					throw new RuntimeException();
				}
			}
			if (failureNum>0){
				failureMsg.insert(0, "，失败 "+failureNum+" 条数据，导入信息如下：");
			}
			addMessage(redirectAttributes, "已成功导入 "+successNum+" 条数据"+failureMsg);
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入房屋失败！失败信息："+e.getMessage());
		}
		return "redirect:" + adminPath + "/business/feeCharge/?repage";
	}



	@RequiresPermissions("business:FeeCharge:edit")
	@RequestMapping(value = "importReceive")
	@Transactional(readOnly = false)
	public String importRoomReceive(MultipartFile file, RedirectAttributes redirectAttributes, HttpServletResponse response){
		try {
			int successNum = 0;
			int failureNum = 0;
			StringBuilder failureMsg = new StringBuilder();
			ImportExcel ei = new ImportExcel(file, 1, 0);
			String[] names =((CommonsMultipartFile) file).getOriginalFilename().split("-");
			List<Community> communityList =null;
			Community currentCommunity ;
			if(names.length>0){
				Community community = new Community();
				community.setName(names[0]);
				communityList =	communityDao.findList(community);

			}
			if(communityList!= null){
				currentCommunity = communityList.get(0);
			}else {
				failureMsg.append("不存在该小区请先在系统中建立相同名称的小区，文件名应为 小区名+ - + 任意");
				return "redirect:" + adminPath + "/business/room/?repage";
			}

			List<FeeChargeHistory> list = ei.getDataList(FeeChargeHistory.class);

			FeeMonth feeMonth = new FeeMonth();
			FeeMonth fm;
			Room room = new Room();
			Building building = new Building();
			for (FeeChargeHistory feeChargeHistory : list){
				try{
					successNum++;
					building.setCommunityId(currentCommunity.getId());
					building.setCode(feeChargeHistory.getBuildingCode());
					List<Building> buildingList = buildingDao.findList(building);
					if(buildingList != null && !buildingList.isEmpty()){
						Building bd =  buildingList.get(0);
						room.setBuildingId(bd.getId());
						room.setCode(feeChargeHistory.getRoomCode());
						List<Room> roomList = roomService.findList(room);
						if(roomList != null && !roomList.isEmpty()){
							for(int i = 0;i<feeChargeHistory.getMonthHistory();i++){
								Date currentMonth  = DateUtils.addMonths(feeChargeHistory.getBeginDate(),i);
								feeMonth.setCurrentMonth(currentMonth);
								List<FeeMonth> feeMonthList = feeMonthDao.selectFeeMonthByCurrentMonth(feeMonth);
								if(null == feeMonthList || feeMonthList.isEmpty()){
									fm = new FeeMonth();
									fm.preInsert();
									fm.setCurrentMonth(currentMonth);
									fm.setIsCurrent("0");
									fm.setStartDate(currentMonth);
									LocalDate lastLocalDate = DateUtils.tranDateToLocalDate(currentMonth).with(TemporalAdjusters.lastDayOfMonth());
									fm.setEndDate(DateUtils.tranLocalDateToDate(lastLocalDate));
									feeMonthDao.insert(fm);
								}else {
									fm = feeMonthList.get(0);
								}

								FeeCharge feeCharge = new FeeCharge();
								feeCharge.setFeeMonthId(fm.getId());
								feeCharge.setRoomId(roomList.get(0).getId());
								feeChargeDao.deleteRepeat(feeCharge);
								feeCharge.setRoomUseFlag(roomList.get(0).getUseFlag());
								feeCharge.setAvgWaterFee(feeChargeHistory.getAvgWater());
								feeCharge.setAvgElecFee(feeChargeHistory.getAvgElec());
								feeCharge.setManageFee(DecimalUtils.multiply(feeChargeHistory.getArea(),feeChargeHistory.getManageFee()));
								feeCharge.setElevatorFee( null == feeChargeHistory.getElevatorFee() ? 0.0:feeChargeHistory.getElevatorFee());
								feeCharge.setSecondPushElecFee(null == feeChargeHistory.getSecondPushFee() ? 0.0:feeChargeHistory.getSecondPushFee());
								feeCharge.setFeebackMoney(0.0);
								feeCharge.setCarMonthFee(0.0);
								Double totalFee = 0.0;
								totalFee = DecimalUtils.add(totalFee
										,feeCharge.getAvgElecFee()
										,feeCharge.getAvgWaterFee()
										,feeCharge.getElevatorFee()
										,feeCharge.getManageFee()
										,feeCharge.getSecondPushElecFee()
										,feeCharge.getCarMonthFee());
								feeCharge.setTotalFee(totalFee);
								feeCharge.setStatus("0");
								Date nowDate = new Date(System.currentTimeMillis());
								feeCharge.setPublishDate(nowDate);
								LocalDate feebackBeginDate = DateUtils.tranDateToLocalDate(nowDate).plusDays(Integer.valueOf(DictUtils.getDictValue("违约金起收天数","feeback_message","0")));
								feeCharge.setFeebackBeginDate(DateUtils.tranLocalDateToDate(feebackBeginDate));
								feeCharge.setFeebackRate(Double.valueOf(DictUtils.getDictValue("违约金比例","feeback_message","0.0001")));
								feeChargeService.save(feeCharge);
								FeeReceive feeReceive = new FeeReceive();
								feeReceive.setFeeCharge(feeCharge);
								feeReceive.setPayAmount(feeCharge.getTotalFee());
								feeReceive.setType("0");
								feeReceive.setCustomerId("0");
								feeCharge.setFeeReceive(feeReceive);
								feeReceiveService.payFeeChargeCash(feeReceive);


							}
						}else {
							throw new RuntimeException();
						}

					}else {
						throw new RuntimeException();
					}

				}catch(ConstraintViolationException ex){
					failureMsg.append(" 导入失败：");
					List<String> messageList = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
					for (String message : messageList){
						failureMsg.append(message+"; ");
						failureNum++;
					}
				}catch (Exception ex) {
					failureMsg.append(" 导入失败："+ex.getMessage());
					throw new RuntimeException();
				}
			}
			if (failureNum>0){
				failureMsg.insert(0, "，失败 "+failureNum+" 条数据，导入信息如下：");
			}
			addMessage(redirectAttributes, "已成功导入 "+successNum+" 条数据"+failureMsg);
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入房屋失败！失败信息："+e.getMessage());
		}
		return "redirect:" + adminPath + "/business/feeCharge/?repage";
	}


}